package com.suredy.app.porject.export;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.suredy.app.porject.constants.ContractStatus;
import com.suredy.app.porject.constants.ContractType;
import com.suredy.app.porject.export.model.CompletedContractLRModel;
import com.suredy.app.porject.model.Contract;
import com.suredy.app.porject.model.ContractMoney;
import com.suredy.app.porject.service.ContractSrv;

/**
 * 完工项目毛利率统计
 * 
 * @author VIVID.G
 * @since 2016-2-29
 * @version v0.1
 */
@Controller
@RequestMapping("/completed-contract-lr")
public class CompletedContractLR extends BaseExportorCtrl {

	@Autowired
	private ContractSrv contractSrv;

	// 表头行数
	private final int TITLE_ROWS = 2;

	@RequestMapping()
	public String index(@DateTimeFormat(pattern = "yyyy-MM-dd") Date dataStart, @DateTimeFormat(pattern = "yyyy-MM-dd") Date dataEnd, Model model) {
		String view = "app/export/completed-contract-lr";

		if (dataStart == null || dataEnd == null) {
			dataStart = this.getYearStart(this.getThisYear());
			dataEnd = this.getYearEnd(this.getThisYear());
		}

		dataStart = this.toDateStart(dataStart);
		dataEnd = this.toDateEnd(dataEnd);

		model.addAttribute("dataStart", dataStart);
		model.addAttribute("dataEnd", dataEnd);
		model.addAttribute("data", this.getData(dataStart, dataEnd));

		return view;
	}

	@RequestMapping(value = "/export", method = RequestMethod.GET)
	public void export(@DateTimeFormat(pattern = "yyyy-MM-dd") Date dataStart, @DateTimeFormat(pattern = "yyyy-MM-dd") Date dataEnd, HttpServletRequest req, HttpServletResponse resp) {
		if (dataStart == null || dataEnd == null) {
			dataStart = this.getYearStart(this.getThisYear());
			dataEnd = this.getYearEnd(this.getThisYear());
		}

		dataStart = this.toDateStart(dataStart);
		dataEnd = this.toDateEnd(dataEnd);

		List<CompletedContractLRModel> data = this.getData(dataStart, dataEnd);

		if (data == null || data.isEmpty())
			return;

		this.doExport(dataStart, dataEnd, req, resp, data);
	}

	@SuppressWarnings("unchecked")
	private List<CompletedContractLRModel> getData(Date start, Date end) {
		String ql = "SELECT T FROM Contract T WHERE T.status=? AND T.type IN (:TYPE) AND ((T.start>=? and T.start<=?) OR (T.end>=? and T.end<=?))";

		List<CompletedContractLRModel> ret = new ArrayList<CompletedContractLRModel>();
		int page = 1;
		List<Object> params = new ArrayList<Object>();

		params.add(ContractStatus.COMPLETED);

		String TYPE = "";
		for (ContractType t : ContractType.MAIN_CONTRACT_TYPES) {
			if (!StringUtils.isBlank(TYPE))
				TYPE += ",";

			TYPE += "?";

			params.add(t);
		}
		ql = ql.replace(":TYPE", TYPE);

		params.add(start);
		params.add(end);
		params.add(start);
		params.add(end);

		while (true) {
			List<Contract> data = (List<Contract>) this.contractSrv.readByQL(ql, page++, 30, params.toArray());

			if (data == null || data.isEmpty())
				break;

			for (Contract c : data) {
				CompletedContractLRModel model = this.createModel(c);

				if (model == null)
					continue;

				ret.add(model);
			}
		}

		return ret.isEmpty() ? null : ret;
	}

	private void doExport(Date start, Date end, HttpServletRequest req, HttpServletResponse resp, List<CompletedContractLRModel> data) {
		if (data == null)
			return;

		String fileName = this.datetimeFormat(start, "yyyy.MM.dd") + "~" + this.datetimeFormat(end, "yyyy.MM.dd") + "工程完工项目毛利计算表";

		WritableWorkbook book = null;

		try {
			WritableSheet sheet = null;

			book = this.createWorkbook(req, resp, fileName);

			int indexOfSheet = 0;
			int rowCount = this.TITLE_ROWS;
			int readed = 0;

			do {
				sheet = this.createSheet(book, indexOfSheet++, start, end);

				if (sheet == null)
					break;

				if (data == null)
					break;

				for (; readed < data.size(); readed++) {
					if (++rowCount > this.MAX_LINE_OF_ONE_SHEET) {
						rowCount = this.TITLE_ROWS;
						break;
					}

					CompletedContractLRModel d = data.get(readed);

					this.writeData(sheet, rowCount - 1, d);
				}
			} while (readed < data.size());

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (book != null) {
				try {
					book.write();
					book.close();
				} catch (Exception e) {
				}
			}
		}
	}

	private WritableSheet createSheet(WritableWorkbook book, int indexOfSheet, Date start, Date end) throws RowsExceededException, WriteException {
		WritableSheet sheet = super.createSheet(book, indexOfSheet);

		if (sheet == null)
			return null;

		WritableFont t = new WritableFont(WritableFont.ARIAL, 14, WritableFont.BOLD);
		WritableFont h = new WritableFont(WritableFont.ARIAL);
		h.setBoldStyle(WritableFont.BOLD);

		WritableCellFormat title = this.createCellFormat(null, null);
		title.setFont(t);

		WritableCellFormat head = this.createCellFormat(null, null);
		head.setFont(h);

		sheet.mergeCells(0, 0, 16, 0);
		sheet.addCell(new Label(0, 0, this.datetimeFormat(start, "yyyy.MM.dd") + "~" + this.datetimeFormat(end, "yyyy.MM.dd") + "工程完工项目毛利计算表", title));

		sheet.addCell(new Label(0, 1, "序号", head));
		sheet.addCell(new Label(1, 1, "项目编码", head));
		sheet.addCell(new Label(2, 1, "合同名称", head));
		sheet.addCell(new Label(3, 1, "实际工期", head));
		sheet.addCell(new Label(4, 1, "建设单位", head));
		sheet.addCell(new Label(5, 1, "完工情况", head));
		sheet.addCell(new Label(6, 1, "合同金额（元）", head));
		sheet.addCell(new Label(7, 1, "结算价金额（元）", head));
		sheet.addCell(new Label(8, 1, "任务书金额（元）", head));
		sheet.addCell(new Label(9, 1, "分包金额（元）", head));
		sheet.addCell(new Label(10, 1, "材料费金额（元）", head));
		sheet.addCell(new Label(11, 1, "其他费用金额（元）", head));
		sheet.addCell(new Label(12, 1, "毛利（元）", head));
		sheet.addCell(new Label(13, 1, "毛利占结算金额的百分比", head));
		sheet.addCell(new Label(14, 1, "项目负责人", head));
		sheet.addCell(new Label(15, 1, "实施单位", head));
		sheet.addCell(new Label(16, 1, "备注", head));

		return sheet;
	}

	private void writeData(WritableSheet sheet, int row, CompletedContractLRModel data) throws RowsExceededException, WriteException {
		if (sheet == null || data == null)
			return;

		int col = 0;

		this.writeCell(sheet, row, col++, row - this.TITLE_ROWS + 1);
		this.writeCell(sheet, row, col++, data.getNo());
		this.writeCell(sheet, row, col++, data.getName());
		this.writeCell(sheet, row, col++, data.getGongQi());
		this.writeCell(sheet, row, col++, data.getCompanyA());
		this.writeCell(sheet, row, col++, data.getCompleted());
		this.writeCell(sheet, row, col++, data.getPriceString());
		this.writeCell(sheet, row, col++, data.getJsPrice());
		this.writeCell(sheet, row, col++, data.getTaskPrice());
		this.writeCell(sheet, row, col++, data.getSubPrice());
		this.writeCell(sheet, row, col++, data.getMaterialPrice());
		this.writeCell(sheet, row, col++, data.getOtherPrice());
		this.writeCell(sheet, row, col++, data.getLr());
		this.writeCellOfPercent(sheet, row, col++, data.getLrRatio());
		this.writeCell(sheet, row, col++, data.getHeader());
		this.writeCell(sheet, row, col++, data.getCompanyB());
		this.writeCell(sheet, row, col++, data.getRemark());
	}

	private CompletedContractLRModel createModel(Contract data) {
		if (data == null || !this.isContractCompleted(data))
			return null;

		CompletedContractLRModel model = new CompletedContractLRModel();

		model.setNo(data.getNo());
		model.setName(data.getName());
		model.setGongQi(this.getShijiGongQi(data));
		model.setCompanyA(data.getCompanyA());
		model.setCompleted("完工");
		model.setPrice(data.getPrice());
		model.setPriceString(data.getPriceString());
		model.setJsPrice(data.getClearingPrice());
		model.setTaskPrice(this.getTaskPrice(data));
		model.setSubPrice(this.getSubPrice(data));
		model.setMaterialPrice(this.getMaterialPrice(data));
		model.setOtherPrice(this.getOtherPrice(data));
		model.setHeader(data.getXiangmuHeader() == null ? null : data.getXiangmuHeader().getName());
		model.setCompanyB(data.getCompanyB());
		model.setRemark(data.getRemark());

		return model;
	}

	/**
	 * 判断合同是否已经完工结算
	 * 
	 * @return
	 */
	private boolean isContractCompleted(Contract c) {
		if (c == null)
			return false;

		return c.isContractCompleted();
	}

	/**
	 * 实际工期
	 * 
	 * @param data
	 * @return
	 */
	private String getShijiGongQi(Contract data) {
		if (data == null)
			return null;

		String gq = "";

		if (data.getStart() != null)
			gq += this.datetimeFormat(data.getStart(), "yyyy.MM.dd");

		if (data.getEnd() != null) {
			if (!StringUtils.isBlank(gq))
				gq += "-";

			gq += this.datetimeFormat(data.getEnd(), "yyyy.MM.dd");
		}

		return StringUtils.isBlank(gq) ? null : gq;
	}

	private Double getTaskPrice(Contract data) {
		if (data == null || data.getSubContracts() == null)
			return null;

		Double ret = null;

		for (Contract sub : data.getSubContracts()) {
			if (sub.getPrice() == null)
				continue;

			if (!ContractType.TASK_CONTRACT.equals(sub.getType()))
				continue;

			if (ret == null)
				ret = 0d;

			ret += sub.getPrice();
		}

		return ret;
	}

	private Double getSubPrice(Contract data) {
		if (data == null || data.getSubContracts() == null)
			return null;

		Double ret = null;

		for (Contract sub : data.getSubContracts()) {
			if (sub.getPrice() == null)
				continue;

			ContractType[] subType = {ContractType.SUB_PROFESSIONAL_CONTRACT, ContractType.SUB_SERVICE_CONTRACT};

			if (!ArrayUtils.contains(subType, sub.getType()))
				continue;

			if (ret == null)
				ret = 0d;

			ret += sub.getPrice();
		}

		return ret;
	}

	private Double getMaterialPrice(Contract data) {
		if (data == null || data.getSubContracts() == null)
			return null;

		Double ret = null;

		for (Contract sub : data.getSubContracts()) {
			if (sub.getPrice() == null)
				continue;

			if (!ContractType.MATERIAL_CONTRACT.equals(sub.getType()))
				continue;

			if (ret == null)
				ret = 0d;

			ret += sub.getPrice();
		}

		return ret;
	}

	private Double getOtherPrice(Contract data) {
		if (data == null || data.getMoney() == null)
			return null;

		Double ret = null;

		for (ContractMoney m : data.getMoney()) {
			// 需要回收（退回）的资金不再计算之列
			if (m.getGaveBack() != null)
				continue;

			if (m.getTotal() == null)
				continue;

			// 只计算费用支出
			if (!Boolean.TRUE.equals(m.getPayOut()))
				continue;

			if (ret == null)
				ret = 0d;

			ret += m.getTotal();
		}

		return ret;
	}

}
